import {
  HttpException,
  HttpStatus,
  Inject,
  Injectable,
  Logger,
} from '@nestjs/common';
import { LoginUserDto, RegisterUserDto } from './dto/create-user.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { Like, Repository } from 'typeorm';
import { RedisService } from 'src/redis/redis.service';
import { md5 } from 'src/utils/md5';
import { EmailService } from 'src/email/email.service';
import { Role } from './entities/role.entity';
import { Permission } from './entities/permission.entity';
import { LoginUserVo } from './vo/login-user.vo';
import { UpdateUserDto } from './dto/update-user.dto';
import { UserInfoVo } from './vo/user-info.vo';
import { UpdatePasswordDto } from './dto/update-password.dto';

@Injectable()
export class UserService {
  private logger = new Logger();

  @InjectRepository(User)
  private userRepository: Repository<User>;

  @InjectRepository(Role)
  private roleRepository: Repository<Role>;

  @InjectRepository(Permission)
  private permissionRepository: Repository<Permission>;

  @Inject(RedisService)
  private redisService: RedisService;

  @Inject(EmailService)
  private emailService: EmailService;

  async register(registerUserDto: RegisterUserDto) {
    const captcha = await this.redisService.get(
      `captcha—_${registerUserDto.email}`,
    );
    if (!captcha) {
      this.logger.error('验证码已过期');
      throw new HttpException('验证码已过期', HttpStatus.BAD_REQUEST);
    }

    if (captcha !== registerUserDto.captcha) {
      this.logger.error('验证码错误');
      throw new HttpException('验证码错误', HttpStatus.BAD_REQUEST);
    }

    const user = await this.userRepository.findOne({
      where: {
        username: registerUserDto.username,
      },
    });

    if (user) {
      this.logger.error('用户名已存在');
      throw new HttpException('用户名已存在', HttpStatus.BAD_REQUEST);
    }
    const newUser = new User();
    newUser.username = registerUserDto.username;
    newUser.password = md5(registerUserDto.password);
    newUser.email = registerUserDto.email;
    newUser.nickName = registerUserDto.nickName;
    newUser.phoneNumber = registerUserDto.phoneNumber;

    try {
      await this.userRepository.save(newUser);
      return '注册成功';
    } catch (error) {
      this.logger.error(error);
      throw new HttpException('注册失败', HttpStatus.BAD_REQUEST);
    }
  }

  async login(user: LoginUserDto, isAdmin: boolean) {
    const userInfo = await this.userRepository.findOne({
      where: {
        username: user.username,
        isAdmin: isAdmin ? 1 : 0,
      },
      relations: ['roles', 'roles.permissions'],
    });

    if (!userInfo) {
      this.logger.error('用户名不存在');
      throw new HttpException('用户名不存在', HttpStatus.BAD_REQUEST);
    }

    if (userInfo.password !== md5(user.password)) {
      this.logger.error('密码错误');
      throw new HttpException('密码错误', HttpStatus.BAD_REQUEST);
    }

    if (userInfo.isFrozen) {
      this.logger.error('用户已被冻结');
      throw new HttpException('用户已被冻结', HttpStatus.BAD_REQUEST);
    }
    const vo = new LoginUserVo();
    vo.userInfo = {
      id: userInfo.id,
      username: userInfo.username,
      password: userInfo.password,
      email: userInfo.email,
      isAdmin: userInfo.isAdmin,
      isFrozen: userInfo.isFrozen,
      nickName: userInfo.nickName,
      phoneNumber: userInfo.phoneNumber,
      createTime: userInfo.createdAt,
      roles: userInfo.roles.map((item) => item.name),
      permissions: userInfo.roles.reduce((pre, cur) => {
        cur.permissions.forEach((item) => {
          if (!pre.includes(item.code)) {
            pre.push(item.code);
          }
        });
        return pre;
      }, []),
    };
    return vo;
  }

  async getCaptcha(email: string) {
    const captcha = Math.random().toString().slice(-6);
    await this.redisService.set(`captcha—_${email}`, captcha, 60 * 5);
    try {
      await this.emailService.sendEmail(
        email,
        '注册验证码',
        `<p>您的注册验证码为：${captcha}</p>`,
      );
    } catch (error) {
      this.logger.error(error);
      throw new HttpException('发送失败', HttpStatus.BAD_REQUEST);
    }

    console.log(captcha);
    return '发送成功';
  }

  async initData() {
    const user1 = new User();
    user1.username = 'zhangsan';
    user1.password = md5('111111');
    user1.email = 'xxx@xx.com';
    user1.isAdmin = 1;
    user1.nickName = '张三';
    user1.phoneNumber = '13233323333';

    const user2 = new User();
    user2.username = 'lisi';
    user2.password = md5('222222');
    user2.email = 'yy@yy.com';
    user2.nickName = '李四';

    const role1 = new Role();
    role1.name = '管理员';

    const role2 = new Role();
    role2.name = '普通用户';

    const permission1 = new Permission();
    permission1.code = 'ccc';
    permission1.description = '访问 ccc 接口';

    const permission2 = new Permission();
    permission2.code = 'ddd';
    permission2.description = '访问 ddd 接口';

    user1.roles = [role1];
    user2.roles = [role2];

    role1.permissions = [permission1, permission2];
    role2.permissions = [permission1];
    await this.permissionRepository.save([permission1, permission2]);
    await this.roleRepository.save([role1, role2]);
    await this.userRepository.save([user1, user2]);
  }

  async list(
    page: number,
    size: number,
    username: string,
    nickName: string,
    email: string,
  ) {
    const skipCount = (page - 1) * size;
    const condition: Record<string, any> = {};
    if (username) {
      condition.username = Like(`%${username}%`);
    }
    if (nickName) {
      condition.nickName = Like(`%${nickName}%`);
    }
    if (email) {
      condition.email = Like(`%${email}%`);
    }

    const [list, total] = await this.userRepository.findAndCount({
      select: [
        'id',
        'username',
        'nickName',
        'email',
        'phoneNumber',
        'isAdmin',
        'isFrozen',
        'headPic',
      ],

      where: condition,
      skip: skipCount,
      take: size,
    });

    return {
      list,
      total,
    };
  }
  async info(id: number) {
    const user = await this.userRepository.findOne({
      where: {
        id: id,
      },
    });
    if (!user) {
      this.logger.error('用户不存在');
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }
    const vo = new UserInfoVo();
    vo.id = user.id;
    vo.username = user.username;
    vo.email = user.email;
    vo.nickName = user.nickName;
    vo.phoneNumber = user.phoneNumber;
    vo.createTime = user.createdAt;
    return vo;
  }

  async update(id: number, user: UpdateUserDto) {
    const captcha = await this.redisService.get(`captcha—_${user.email}`);
    if (!captcha) {
      this.logger.error('验证码已过期');
      throw new HttpException('验证码已过期', HttpStatus.BAD_REQUEST);
    }

    if (captcha !== user.captcha) {
      this.logger.error('验证码错误');
      throw new HttpException('验证码错误', HttpStatus.BAD_REQUEST);
    }

    const userInfo = await this.userRepository.findOne({
      where: {
        id: id,
      },
    });
    if (!userInfo) {
      this.logger.error('用户不存在');
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }

    userInfo.email = user.email;
    if (user.nickName) {
      userInfo.nickName = user.nickName;
    }
    if (user.headPic) {
      userInfo.headPic = user.headPic;
    }

    try {
      await this.userRepository.save(userInfo);
      return '修改成功';
    } catch (error) {
      this.logger.error(error);
      throw new HttpException('修改失败', HttpStatus.BAD_REQUEST);
    }
  }

  async updatePassword(id: number, user: UpdatePasswordDto) {
    const captcha = await this.redisService.get(`captcha—_${user.email}`);
    if (!captcha) {
      this.logger.error('验证码已过期');
      throw new HttpException('验证码已过期', HttpStatus.BAD_REQUEST);
    }
    if (captcha !== user.captcha) {
      this.logger.error('验证码错误');
      throw new HttpException('验证码错误', HttpStatus.BAD_REQUEST);
    }

    const userInfo = await this.userRepository.findOne({
      where: {
        id: id,
      },
    });
    if (!userInfo) {
      this.logger.error('用户不存在');
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }
    userInfo.password = md5(user.password);

    try {
      await this.userRepository.save(userInfo);
      return '修改成功';
    } catch (error) {
      this.logger.error(error);
      throw new HttpException('修改失败', HttpStatus.BAD_REQUEST);
    }
  }

  async freeze(id: number) {
    const userInfo = await this.userRepository.findOne({
      where: {
        id: id,
      },
    });
    if (!userInfo) {
      this.logger.error('用户不存在');
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }
    userInfo.isFrozen = 1;
    try {
      await this.userRepository.save(userInfo);
      return '冻结成功';
    } catch (error) {
      this.logger.error(error);
      throw new HttpException('冻结失败', HttpStatus.BAD_REQUEST);
    }
  }
}
